#include "read_boy_confg.h"
#include "readboy_epd_5_83A.h"
#include "read_boy.h"

#if defined(READ_BOY_DEV_5_83A) 



drv_Base_t my_drv_base;

unsigned char epd_data[600 * 448/8];

void my_drv_base_init(){
    my_drv_base.iLut = 15;
    my_drv_base.sleeping = 1;
    my_drv_base.epdWidth = 600;
    my_drv_base.epdHeight = 448;
    //my_drv_base.idleFastRf = 350;
    //my_drv_base.idleSlowRf = 1300;
    
    my_drv_base.epdFull = 1;// //是partical模式/快速刷新模式 0快刷, 1慢刷
    my_drv_base.GreyScalingHighQuality = 0;
    my_drv_base.Power_is_on = 0  ; //初始为未上电
    my_drv_base.GreyScaling = 0; //是否正在灰度显示
    my_drv_base.part_mode = 1;
    
    my_drv_base.in_trans = 0;
    my_drv_base._quality = 3; //灰度显示品质 默认2 0,2-高品质 1,3-低品质高兼容性. 0,1使用bayer灰度二值表 2,3使用floyd算法   
    my_drv_base.lastRefresh = 0;
    
    my_drv_base.buf_2nd = epd_data;
    
    my_drv_base.drv_fullpart = &read_boy_5_83a_drv_fullpart;
    my_drv_base.drv_setDepth = &read_boy_5_83a_drv_setDepth;
    my_drv_base.drv_sleep = &read_boy_5_83a_drv_sleep;
////    my_drv_base.lut_Init = &read_boy_4_2a_drv_SetLut;//===============================================================
    my_drv_base.drv_dispWriter = &read_boy_5_83a_drv_dispWriter;
//    
//    read_boy_4_2b_drv();

//    read_boy_4_2b_drv_init();
}

const   unsigned char  lut_20_LUTC[] =
{  0x01, 0x00, 0x00, 0x1B, 0x10, 0x0F, 0x0A, 0x0A, 0x0F, 0x10, 0x1B};
const   unsigned char  lut_20_LUTCFAST[] =
{  0x01, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const   unsigned char  lut_21_LUTB[] =//000
{  0x01, 0x21, 0x21, 0x21, 0x21, 0x1B, 0x14, 0x13, 0x12, 0x00, 0x00, 0x10, 0x1E};
const   unsigned char  lut_21_LUTBFAST[] =
{  0x01, 0x12, 0x12, 0x12, 0x10, 0x1f, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x00};
const   unsigned char  lut_22_LUTW[] =//011
{  0x01, 0x11, 0x21, 0x21, 0x22, 0x1B, 0x14, 0x13, 0x12, 0x00, 0x00, 0x10, 0x1E};
const   unsigned char  lut_22_LUTWFAST[] =
{  0x01, 0x21, 0x21, 0x21, 0x20, 0x1f, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 0x00};
const   unsigned char  lut_23_LUTG1[] =//001
{  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const   unsigned char  lut_24_LUTG2[] =//010
{  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const   unsigned char  lut_25_LUTR0[] =//100//WW
{  0x01, 0x12, 0x12, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03};
const   unsigned char  lut_26_LUTR1[] =//101//BB
{  0x00/*0x01*/, 0x21, 0x21, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02};
const   unsigned char  lut_27_LUTR2[] =//110
{  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const   unsigned char  lut_28_LUTR3[] =//111//局刷
{  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const   unsigned char  lut_29_LUTXON[] =
{  0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const   unsigned char  customGrey[] =
{  0x00, 0x01, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0a, 0x0c, 0x0e, 0x11, 0x14, 0x17, 0x1a, 0x1e,
   0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
const   unsigned char *drv_luts[10]={
  lut_20_LUTC,lut_21_LUTB,lut_22_LUTW,lut_23_LUTG1,lut_24_LUTG2,
  lut_25_LUTR0,lut_26_LUTR1,lut_27_LUTR2,lut_28_LUTR3,lut_29_LUTXON
};
const unsigned char *drv_luts_fast[10]={
  lut_20_LUTCFAST,lut_21_LUTBFAST,lut_22_LUTWFAST,lut_23_LUTG1,lut_24_LUTG2,
  lut_25_LUTR0,lut_26_LUTR1,lut_27_LUTR2,lut_28_LUTR3,lut_29_LUTXON
};


void read_boy_5_83a_drv_sendLut(int lutid){
  int lutlen=13,lutlen2=247;
  if(lutid==0){lutlen=11;lutlen2=209;}
  else if(lutid==9){lutlen=10;lutlen2=190;}
  readboyEpdBase_boy_epdCmd(0x20+lutid);
  if(my_drv_base.epdFull){
    for(int i=0;i<lutlen;i++){
      readboyEpdBase_boy_epdParam(drv_luts[lutid][i]);//(luts[lutid]+i));
    }
  }
  else{
    for(int i=0;i<lutlen;i++){
      if(lutid==1 && i==5) readboyEpdBase_boy_epdParam(customGrey[my_drv_base.iLut+ my_drv_base.GreyScalingHighQuality]);//(customGrey+iLut+greyscalingHighQuality));
      else
      readboyEpdBase_boy_epdParam(drv_luts_fast[lutid][i]);//(luts_fast[lutid]+i));
    }
  }
  for(int i=0;i<lutlen2;i++){
    readboyEpdBase_boy_epdParam(0);
  }
}


void read_boy_5_83a_drv_epd_init(){
  if(!my_drv_base.Power_is_on) readboyEpdBase_Reset(20); //Reset(); //设定为已上电
  readboyEpdBase_boy_epdCmd(0x01);
  readboyEpdBase_boy_epdParam(0x37);
  readboyEpdBase_boy_epdParam(0x00);
  readboyEpdBase_boy_epdParam(0x07);
  readboyEpdBase_boy_epdParam(0x07);
  readboyEpdBase_boy_epdCmd(0x00);
  readboyEpdBase_boy_epdParam(0xcf);
  readboyEpdBase_boy_epdParam(0x88);
  readboyEpdBase_boy_epdCmd(0x06);
  readboyEpdBase_boy_epdParam(0xc7);
  readboyEpdBase_boy_epdParam(0xcc);
  readboyEpdBase_boy_epdParam(0x28);
  readboyEpdBase_boy_epdCmd(0x30);
  readboyEpdBase_boy_epdParam(0x3a);
  readboyEpdBase_boy_epdCmd(0x41);
  readboyEpdBase_boy_epdParam(0x00);
  readboyEpdBase_boy_epdCmd(0x50);
  readboyEpdBase_boy_epdParam(0x77);
  readboyEpdBase_boy_epdCmd(0x60);
  readboyEpdBase_boy_epdParam(0x22);
  readboyEpdBase_boy_epdCmd(0x61);
  readboyEpdBase_boy_epdParam(0x02);
  readboyEpdBase_boy_epdParam(0x58);
  readboyEpdBase_boy_epdParam(0x01);
  readboyEpdBase_boy_epdParam(0xc0);
  readboyEpdBase_boy_epdCmd(0x82);
  readboyEpdBase_boy_epdParam(0x28);
  for(int i=0;i<10;i++){
    read_boy_5_83a_drv_sendLut(i);
  }
  readboyEpdBase_boy_epdCmd(0xe5);
  readboyEpdBase_boy_epdParam(0x03);
}

void read_boy_5_83a_drv_epd_sendZoneInfo(){
    readboyEpdBase_boy_epdCmd(0x91);
    //send area info
    readboyEpdBase_boy_epdCmd(0x90);
    readboyEpdBase_boy_epdParam(0x00);
    readboyEpdBase_boy_epdParam(0x00);
    readboyEpdBase_boy_epdParam(0x02);
    readboyEpdBase_boy_epdParam(0x57);
    readboyEpdBase_boy_epdParam(0x00);
    readboyEpdBase_boy_epdParam(0x00);
    readboyEpdBase_boy_epdParam(0x01);
    readboyEpdBase_boy_epdParam(0xbf);
    readboyEpdBase_boy_epdParam(0x01);
}

void read_boy_5_83a_drv_epd_sendWriter(read_boy_drv_dispWriter_t* f){
    readboyEpdBase_boy_epdCmd(0x10);  //Then write image data 显示数据
#ifdef READGUY_583A_DUAL_BUFFER
    if(my_drv_base.epdFull || my_drv_base.buf_2nd==NULL || my_drv_base.GreyScalingHighQuality){
#endif
      for(int i=0;i<my_drv_base.epdWidth*my_drv_base.epdHeight/8;i++){ //fill 0x03 for test
        uint8_t dat=0,dat_r=f(i);
        dat |= ((dat_r&0x80)?0x30:0);
        dat |= ((dat_r&0x40)?0x03:0);
        readboyEpdBase_boy_epdParam(dat);
        dat&=0;
        dat |= ((dat_r&0x20)?0x30:0);
        dat |= ((dat_r&0x10)?0x03:0);
        readboyEpdBase_boy_epdParam(dat);
        dat&=0;
        dat |= ((dat_r&0x08)?0x30:0);
        dat |= ((dat_r&0x04)?0x03:0);
        readboyEpdBase_boy_epdParam(dat);
        dat&=0;
        dat |= ((dat_r&0x02)?0x30:0);
        dat |= ((dat_r&0x01)?0x03:0);
        readboyEpdBase_boy_epdParam(dat);
#ifdef READGUY_583A_DUAL_BUFFER
        my_drv_base.buf_2nd[i]=dat_r;
      }
    }
    else{
      for(int i=0;i<my_drv_base.epdWidth*my_drv_base.epdHeight/8;i++){ //fill 0x03 for test
        //guy_epdParam(0x03); //for data test
        uint8_t dat=0,dat_r=f(i);
        dat |= ((dat_r&0x80)?((my_drv_base.buf_2nd[i]&0x80)?0x40:0x30):((my_drv_base.buf_2nd[i]&0x80)?0x00:0x50));
        //0x3?黑->白色, 0x0?白->黑色 0x4? 白->白色 0x5? 黑->黑色
        dat |= ((dat_r&0x40)?((my_drv_base.buf_2nd[i]&0x40)?0x4:0x3):((my_drv_base.buf_2nd[i]&0x40)?0x0:0x5));
        readboyEpdBase_boy_epdParam(dat);
        dat&=0;
        dat |= ((dat_r&0x20)?((my_drv_base.buf_2nd[i]&0x20)?0x40:0x30):((my_drv_base.buf_2nd[i]&0x20)?0x00:0x50));
        dat |= ((dat_r&0x10)?((my_drv_base.buf_2nd[i]&0x10)?0x4:0x3):((my_drv_base.buf_2nd[i]&0x10)?0x0:0x5));
        readboyEpdBase_boy_epdParam(dat);
        dat&=0;
        dat |= ((dat_r&0x8)?((my_drv_base.buf_2nd[i]&0x8)?0x40:0x30):((my_drv_base.buf_2nd[i]&0x8)?0x00:0x50));
        dat |= ((dat_r&0x4)?((my_drv_base.buf_2nd[i]&0x4)?0x4:0x3):((my_drv_base.buf_2nd[i]&0x4)?0x0:0x5));
        readboyEpdBase_boy_epdParam(dat);
        dat&=0;
        dat |= ((dat_r&0x2)?((my_drv_base.buf_2nd[i]&0x2)?0x40:0x30):((my_drv_base.buf_2nd[i]&0x2)?0x00:0x50));
        dat |= ((dat_r&0x1)?((my_drv_base.buf_2nd[i]&0x1)?0x4:0x3):((my_drv_base.buf_2nd[i]&0x1)?0x0:0x5));
        readboyEpdBase_boy_epdParam(dat);
        my_drv_base.buf_2nd[i]=dat_r;
      }
#endif
    }
}

void read_boy_5_83a_drv_fullpart(bool part){ //初始化慢刷/快刷功能
  if(my_drv_base.lastRefresh) return;
  if(!my_drv_base.Power_is_on) part=0;
  my_drv_base.epdFull=!part;
  if(my_drv_base.epdFull) my_drv_base.iLut=15;
}

void read_boy_5_83a_drv_setDepth(uint8_t i){
  if(!my_drv_base.Power_is_on) return; //不支持切换到快刷的情形
  my_drv_base.epdFull=0; my_drv_base.iLut = i?(i>15?15:i):15;  //如果需要, 改成自己的代码
}

void read_boy_5_83a_drv_dispWriter(read_boy_drv_dispWriter_t *f,uint8_t m){ //单色刷新

  if(m&1){//stage 1
    if(my_drv_base.lastRefresh) read_boy_5_83a_drv_dispWriter(f,2);
    //add driver code...
      readboyEpdBase_BeginTransfer();
    if(my_drv_base.epdFull){
      if(!my_drv_base.Power_is_on){
        my_drv_base.epdFull=0; //发送快刷的lut
        read_boy_5_83a_drv_epd_init();//epd_init();
        my_drv_base.epdFull=1; //发送快刷的lut
        readboyEpdBase_boy_epdCmd(0x04); //power on
        readboyEpdBase_EndTransfer();
        readboyEpdBase_boy_epdBusy(-60);
        readboyEpdBase_BeginTransfer();
        readboyEpdBase_boy_epdCmd(0x10);
        for(int i=0;i<my_drv_base.epdWidth*my_drv_base.epdHeight/2;i++){ //fill 0x33
          readboyEpdBase_boy_epdParam(0x33);
        }
        my_drv_base.Power_is_on = 1;//epd_PowerOn=1; //设定为已上电
      }
      else{ //full refresh need power on
        readboyEpdBase_boy_epdCmd(0x04); //power on
        readboyEpdBase_EndTransfer();
        readboyEpdBase_boy_epdBusy(-60);
        readboyEpdBase_BeginTransfer();
      }
      read_boy_5_83a_drv_epd_sendZoneInfo();//epd_sendZoneInfo();
      readboyEpdBase_boy_epdCmd(0x10);  //Then write image data
      for(int i=0;i<my_drv_base.epdWidth*my_drv_base.epdHeight/2;i++){ //fill 0x03 for test
        readboyEpdBase_boy_epdParam(0x33); //for test
      }
      readboyEpdBase_boy_epdCmd(0x92);
      read_boy_5_83a_drv_epd_init();
      //epd_init(); //repeat call in GxEPD2
      read_boy_5_83a_drv_epd_sendWriter(f);  //write image data
    }
    else{
      read_boy_5_83a_drv_epd_init();
      //Power on fx
      readboyEpdBase_boy_epdCmd(0x04);
      readboyEpdBase_EndTransfer();
      readboyEpdBase_boy_epdBusy(-60);
      readboyEpdBase_BeginTransfer();
      read_boy_5_83a_drv_epd_sendZoneInfo();
      read_boy_5_83a_drv_epd_sendWriter(f);
      readboyEpdBase_boy_epdCmd(0x92);
      read_boy_5_83a_drv_epd_sendZoneInfo();
    }
    readboyEpdBase_boy_epdCmd(0x12);  //开始刷屏
    readboyEpdBase_EndTransfer();
    my_drv_base.lastRefresh=0;//millis();
  }
  if(m&2){//stage 2
    int ms=0;//millis()-lastRefresh;
    //Serial.printf("epdFull? %d, epd_PowerOn? %d \n",epdFull,epd_PowerOn);
    //int u=epdFull?slowRefTime:fastRefTime;  //全刷:局刷 busy时间
    int u=my_drv_base.epdFull?1600:560;  
    if(ms<u) readboyEpdBase_boy_epdBusy(ms-u);   //对于busy电平为低电平忙碌,高电平正常的屏幕则改为ms-u
    my_drv_base.lastRefresh=0;
    //add driver code...
    readboyEpdBase_BeginTransfer();
    if(my_drv_base.epdFull){
      my_drv_base.epdFull=0; //发送快刷的lut
      read_boy_5_83a_drv_epd_init(); //repeat init in part mode
      my_drv_base.epdFull=1; //发送快刷的lut
      read_boy_5_83a_drv_epd_sendZoneInfo();
      readboyEpdBase_boy_epdCmd(0x10);  //Then write image data
      for(int i=0;i<my_drv_base.epdWidth*my_drv_base.epdHeight/2;i++){ //fill 0x03 for test
        readboyEpdBase_boy_epdParam(0x33); //for test
      }
      readboyEpdBase_boy_epdCmd(0x02); //power off for test...
      //guy_epdBusy(-30);
    }
    else{
      readboyEpdBase_boy_epdCmd(0x92);
      read_boy_5_83a_drv_epd_sendZoneInfo();
      readboyEpdBase_boy_epdCmd(0x10);  //Then write image data 显示数据
      for(int i=0;i<my_drv_base.epdWidth*my_drv_base.epdHeight/2;i++){ //fill 0x03 for test
        readboyEpdBase_boy_epdParam(0x33); //for test:全白
      }
      readboyEpdBase_boy_epdCmd(0x92);
    }
    readboyEpdBase_EndTransfer();
  }
/* test code ,  with stageless ------------------------------------------------------
  if(epdFull){ //慢刷
    BeginTransfer();
    if(!epd_PowerOn){
      epdFull=0; //发送快刷的lut
      epd_init();
      epdFull=1; //发送快刷的lut
      guy_epdCmd(0x04); //power on
      EndTransfer();
      guy_epdBusy(-60);
      BeginTransfer();
      guy_epdCmd(0x10);
      for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/2;i++){ //fill 0x33
        guy_epdParam(0x33);
      }
      epd_PowerOn=1; //设定为已上电
    }
    else{ //full refresh need power on
      guy_epdCmd(0x04); //power on
      EndTransfer();
      guy_epdBusy(-60);
      BeginTransfer();
    }
    epd_sendZoneInfo();
    guy_epdCmd(0x10);  //Then write image data
    for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/2;i++){ //fill 0x03 for test
      guy_epdParam(0x33); //for test
    }
    guy_epdCmd(0x92);
    epd_init();
    //epd_init(); //repeat call in GxEPD2
    epd_sendWriter(f);  //write image data
    guy_epdCmd(0x12);
    EndTransfer();
    guy_epdBusy(-4000);
    BeginTransfer();
    epdFull=0; //发送快刷的lut
    epd_init(); //repeat init in part mode
    epdFull=1; //发送快刷的lut
    epd_sendZoneInfo();
    guy_epdCmd(0x10);  //Then write image data
    for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/2;i++){ //fill 0x03 for test
      guy_epdParam(0x33); //for test
    }
    guy_epdCmd(0x02); //power off for test...
    EndTransfer();
    //guy_epdBusy(-30);
  }
  else{ //partmode
    BeginTransfer();
    epd_init();
    //Power on fx
    guy_epdCmd(0x04);
    EndTransfer();
    guy_epdBusy(-60);
    BeginTransfer();
    epd_sendZoneInfo();
    epd_sendWriter(f);
    guy_epdCmd(0x92);
    epd_sendZoneInfo();
    guy_epdCmd(0x12);  //快刷
    EndTransfer();
    guy_epdBusy(-1000); //1秒钟刷屏时间
    BeginTransfer();
    guy_epdCmd(0x92);
    epd_sendZoneInfo();
    guy_epdCmd(0x10);  //Then write image data 显示数据
    for(int i=0;i<GUY_D_WIDTH*GUY_D_HEIGHT/2;i++){ //fill 0x03 for test
      guy_epdParam(0x33); //for test:全白
    }
    guy_epdCmd(0x92);
    EndTransfer();
  }
// test code ,  with stageless ------------------------------------------------------ */
}


//void read_boy_5_83a_drv_draw16grey_step(read_boy_drv_dispWriter_t * f, int step){
//  if(my_drv_base._quality&1) return readguyEpdBase::drv_draw16grey_step(f,step);
//  if(step==1) drv_fullpart(1);//初始阶段,完成准备工作 //设置为快刷模式
//  greyscalingHighQuality=16; //开启高品质灰度模式
//  iLut=step;
//  drv_dispWriter(f);
//  //DelayMs(10); //未知原因()
//  if(step==15) greyscalingHighQuality=0;//初始阶段,完成准备工作 //设置为快刷模式
//}
void read_boy_5_83a_drv_sleep() { //开始屏幕睡眠
  //if(RST_PIN>=0){ //RST_PIN<0 无法唤醒
    //add driver code...
    readboyEpdBase_boy_epdCmd(0x07); // deep sleep
    readboyEpdBase_boy_epdParam(0xA5);    // check code
  //}
  my_drv_base.Power_is_on = 0;
  my_drv_base.epdFull = 1; //强制设置为慢刷新模式
}





#endif









































